﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics.Contracts;
using Platform.Infrastructure;

namespace System.Linq.Expressions
{
	/// <summary>
	/// Remove a primeira expressão lambda que for encontrada
	/// </summary>
	internal sealed class LambdaExpressionReducer : ExpressionVisitor
	{
		private int stopsWhenReachZero;

		public LambdaExpressionReducer( int max )
		{
			this.stopsWhenReachZero = Math.Max( 1, max );
		}


		protected override Expression VisitUnary( UnaryExpression node )
		{
			switch ( node.NodeType )
			{
				case ExpressionType.Quote:
					return base.Visit( node.Operand );
				default:
					return base.Visit( node );
			}
		}

		protected override Expression VisitLambda<T>( Expression<T> node )
		{
			if ( this.stopsWhenReachZero-- > 0 )
				return base.Visit( node.Body );
			else
				return node;
			//var newNode = ( Expression<T> )base.Visit( node.Body );
			//return node.Body;
		}

		protected override Expression VisitGoto( GotoExpression node )
		{
			return node.Value;	
		}
	}

	public static class LambdaExpressionReducerExtensions
	{
		public static Expression StripLambda( this LambdaExpression lambda )
		{
			return lambda.StripLambda( 1 );
		}

		public static Expression StripLambda( this LambdaExpression lambda, int howMany )
		{
			Arguments.IsNotNull( "lambda", lambda );

			LambdaExpressionReducer reducer = new LambdaExpressionReducer(howMany);
			return reducer.Visit( lambda );
		}
	}
}
